package myws

import (
	"github.com/gorilla/websocket"
	"net/http"
	"encoding/json"
	"time"
    "sync"
    "fmt"
)

type Mesg struct {
    Type    string
    Code    int64
    Api     string
    Msg     string
    Data    []byte
}

type client struct {
    ws  *websocket.Conn
    ch  chan Mesg
    id  string
    ip  string
}

type cliuser struct {
    ID string
    IP string
}

var (
    UpGrader = websocket.Upgrader{
        CheckOrigin: func(r *http.Request) bool { return true },
    }
    clients = make(map[string]*client)
    clientsMu sync.Mutex
)

// ws链接对于http的对外操作接口
func Del_clients(ConnectID string) {
    clientsMu.Lock()
    defer clientsMu.Unlock()
    if cli, ok := clients[ConnectID]; ok {
        cli.ws.Close()
        close(cli.ch)
        delete(clients, ConnectID)
        return
    }
    return 
}

func See_clients() []cliuser {
    clientsMu.Lock()
    defer clientsMu.Unlock()
    var clientsInfo []cliuser
    for id, cli := range clients {
        clientsInfo = append(clientsInfo, cliuser{ID: id, IP: cli.ip})
    }
    return clientsInfo
}


func processValue(v interface{}) int64 {
    if num, ok := v.(float64); ok {
        return int64(num)
        // 使用intNum
    } else {
        // 处理非float64类型的情况
        return 0
    }
}


// ws链接对于http的对外操作接口



func NewTickerFor() {
    ticker := time.NewTicker(60 * time.Second)
    pingMesg := Mesg{
        Type: "ping",
        Code: 200,
        Api: "/api/ws",
    }
    for t := range ticker.C {
        pingMesg.Msg = fmt.Sprintf("%v", t)
        for _, c := range clients {
            err := c.ws.WriteJSON(pingMesg)
            if err != nil {
                clientsMu.Lock()
                close(c.ch)
                delete(clients, c.id)
                clientsMu.Unlock()
            }
        }
    }
}

func NewWsApi(ws *websocket.Conn, ConnectID string, Ipaddr string) {
    defer ws.Close()
    clientsMu.Lock()
    if _, ok := clients[ConnectID]; ok {
        clientsMu.Unlock()
        return
    }
    ch := make(chan Mesg, 30)
    clients[ConnectID] = &client{ws: ws, ch: ch, id: ConnectID, ip: Ipaddr}
    clientsMu.Unlock()
    
    go func() {
        defer func() {
            clientsMu.Lock()
            close(ch)
            delete(clients, ConnectID)
            clientsMu.Unlock()
        }()
        for {
            _, msg, err := ws.ReadMessage()
            if err != nil {
                return 
            }
            var json_data map[string]interface{}
            err = json.Unmarshal(msg, &json_data)
            if err != nil {
                continue
            }
            switch json_data["type"] {
                case "ping":
                    if err := ws.WriteJSON(Mesg{Type: "pong", Code: 200, Msg: "pong"}); err != nil {
                        return
                    }
                case "broadcast":
                    head := json_data["data"].(map[string]interface{})["head"].(map[string]interface{})
                    if cli, ok := clients[fmt.Sprintf("%s", head["_id"])]; ok {
                        data, _ := json.Marshal(json_data["data"])
                        send_data, _ := json.Marshal(Mesg{
                            Type: fmt.Sprintf("%s", json_data["type"]),
                            Api: ConnectID,
                            Code: processValue(json_data["code"]),
                            Data: data,
                        })
                        if err := cli.ws.WriteMessage(websocket.TextMessage, send_data); err != nil {
                            clientsMu.Lock()
                            close(cli.ch)
                            delete(clients, cli.id)
                            clientsMu.Unlock()
                        }
                    }else{
                        data, _ := json.Marshal(map[string]interface{}{
                            "mesg": fmt.Sprintf("<div><span>用户不在线</span></div><div><span>%s</span></div>", head["_id"]), 
                            "type": "notify",
                            "head": map[string]interface{}{
                                "title": "详细信息",
                                "duration": 2500,
                                "dangerouslyUseHTMLString": true,
                            },
                        })
                        send_data, _ := json.Marshal(Mesg{
                            Type: fmt.Sprintf("%s", json_data["type"]),
                            Api: ConnectID,
                            Code: processValue(json_data["code"]),
                            Data: data,
                        })
                        if err := ws.WriteMessage(websocket.TextMessage, send_data); err != nil {
                            return
                        }
                    }
                case "retransmission":
                    data, _ := json.Marshal(json_data["data"])
                    SendWs(Mesg{
                        Type: fmt.Sprintf("%s", json_data["type"]),
                        Api: ConnectID,
                        Code: processValue(json_data["code"]),
                        Data: data,
                    })
                case "UserList":
                    //var uslt []string
                    //for _, v := range clients {
                    //    uslt = append(uslt, v.id)
                    //}
                    data, _ := json.Marshal(See_clients())
                    send_data, _ := json.Marshal(Mesg{
                        Type: "listuser",
                        Api: "",
                        Code: processValue(json_data["code"]),
                        Data: data,
                    })
                    if err := ws.WriteMessage(websocket.TextMessage, send_data); err != nil {
                        return
                    }
            }
        }
    }()
    for v := range ch {
        data, err := json.Marshal(v)
        if err != nil {
            continue
        }
        if err := ws.WriteMessage(websocket.TextMessage, data); err != nil {
            clientsMu.Lock()
            close(ch)
            delete(clients, ConnectID)
            clientsMu.Unlock()
            return
        }   
    }
}

func SendWs(message Mesg) {
    clientsMu.Lock()
    defer clientsMu.Unlock()
	for _, c := range clients {
        select {
            case c.ch <- message:
            default:
            // 通道已满或已关闭，忽略本次消息发送
        }
    }
}